/*
 * @Author: DUST
 * @Date: 2023-11-24 16:58:11
 * @LastEditors: DUST
 * @LastEditTime: 2024-11-11 17:37:09
 * @FilePath: \business-card-system\server\app\controller\BusinessCardUserController.ts
 * @Description:
 * undefined
 */
import { Context } from "koa";
import pagination from "../../utils/pagination";
import BusinessCardUserServeice from "../service/BusinessCardUserService";
import responese from "../../utils/responese";
import BusinessCardUserValidator, {
  BusinessCArdUserItem,
} from "../validator/BusinessCardUserValidator";
import validate from "../../utils/validator";
import uploadFile from "../../utils/upload";
import requestApi from "../../utils/request";
import config from "../config";
import redis from "../../utils/redis";
import fs from "fs";
import path from "path";
import MD5 from "../../utils/MD5";
import request from "request";

interface MiniToken {
  access_token: string;
  expires_in: number;
  startTime?: number;
}

class BusinessCardUserController {
  /**
   * @description: 获取笔记列表
   * @param {Context} ctx：请求体
   */
  public getBusinessCardUserList = async (ctx: Context) => {
    const { pageSize, pageNumber } = pagination.getPageParams(ctx);
    console.log("分页参数：", pageSize, pageNumber);
    // 数据库查询数据
    const { rows, count } =
      await BusinessCardUserServeice.getBusinessCardUserListByPage(
        pageSize,
        pageNumber
      );
    const paginationData = pagination.doPaginate(
      count == 0 ? [] : rows,
      pageSize,
      count,
      pageNumber
    );
    // console.log(paginationData);
    responese.success(ctx, paginationData);
  };
  /**
   * @description: 根据id查询详情内容
   * @param {Context} ctx：请求体
   */
  async getBusinessCardUserDetailsById(ctx: Context) {
    const params = ctx.params;
    // console.log("查询个人信息：params:", params);
    if (isNaN(params.id)) return responese.errorResponese(ctx, "参数类型错误");
    const row = await BusinessCardUserServeice.getBusinessCardUserById(
      params.id
    );
    if (row?.id) return responese.success(ctx, row);

    responese.errorResponese(ctx, "未查询到相关内容");
  }

  public addBusinessCardUser = async (ctx: Context) => {
    const filePath = uploadFile(ctx);
    console.log("file", filePath);
    const { data, msg } = await validate(
      ctx,
      BusinessCardUserValidator.addRules
    );
    if (msg != null) return responese.errorResponese(ctx, msg);
    data.avatar = filePath;
    const [rows, isCreated] =
      await BusinessCardUserServeice.addBusinessCardUser(data);
    console.log("id:", rows?.id, isCreated);
    if (!isCreated)
      return responese.errorResponese(ctx, "该手机号用户已存在，请确认后再添加!");
    if (rows?.id) {
      const tokenObj = await this.getMiniTokenFromRedis(ctx);
      if (tokenObj && tokenObj?.access_token) {
        const qrcodePath = await this.createUserQrcode(
          ctx,
          tokenObj?.access_token,
          {
            id: rows.id,
            unitId: 1,
          }
        );
        const row = await BusinessCardUserServeice.editBusinessCardUser(
          { miniQrcode: qrcodePath },
          rows.id
        );
        console.log("编辑填充二维码地址：", row);
        console.log("qrcodePath", qrcodePath);
        if (row) return responese.success(ctx, null);
      }
      return responese.errorResponese(ctx, "获取小程序token失败", -1, tokenObj);
    }

    return responese.errorResponese(ctx, "新增失败");
  };

  public editBusinessCardUser = async (ctx: Context) => {
    const filePath = uploadFile(ctx, true);
    console.log("file", filePath);
    const {
      data: { name, mobile, wxNumber, avatar, email, job, id, addr, companyName },
      msg,
    } = await validate<BusinessCArdUserItem & { id: number }>(
      ctx,
      BusinessCardUserValidator.editRules
    );
    if (msg) return responese.errorResponese(ctx, msg);
    if (isNaN(id)) return responese.errorResponese(ctx, "传入ID参数类型错误");
    const row = await BusinessCardUserServeice.editBusinessCardUser(
      { name, mobile, wxNumber, email, avatar: filePath || avatar, job, addr, companyName },
      id
    );
    console.log("编辑：", row);
    if (row) return responese.success(ctx, null, "编辑成功");
    responese.errorResponese(ctx, "编辑失败");
  };

  async deleteBusinessCardUser(ctx: Context) {
    const params = ctx.params;
    if (isNaN(params.id))
      return responese.errorResponese(ctx, "id参数类型错误");

    const row = await BusinessCardUserServeice.deleteBusinessCardUser(
      params.id
    );
    if (row) return responese.success(ctx, null);
    responese.errorResponese(ctx, "删除失败");
  }

  public getMiniTokenFromRedis = async (ctx: Context) => {
    let obj: MiniToken | undefined = undefined;
    const minitoken = await redis.get("miniToken");
    if (!minitoken) {
      obj = await this.storageToken(ctx);
    } else {
      const parseObj = JSON.parse(minitoken);
      if (
        parseObj.startTime + parseObj.expires_in * 1000 >
        Number(new Date()) + 100 * 1000
      )
        obj = parseObj;
      else {
        obj = await this.storageToken(ctx);
      }
    }
    console.log("miniToken", obj);
    return obj;
  };

  /**
   * @description: 存储小程序token
   */
  public storageToken = async (ctx: Context) => {
    const token = await this.getMiniTokenFromWx(ctx);
    console.log("storageToken", token);
    if (token.access_token) {
      token.startTime = Number(new Date());
      redis.set("miniToken", JSON.stringify(token));
      return token;
    } else return token;
  };

  /**
   * @description: 获取小程序token
   */
  getMiniTokenFromWx(ctx: Context): Promise<MiniToken> {
    return new Promise(async (resolve) => {
      // 获取token信息
      const res: MiniToken = (await requestApi(
        "get",
        `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${config.mini.appId}&secret=${config.mini.secret}`
      )) as MiniToken;
      console.log(res);
      resolve(res);
    });
  }
  /**
   * @description: 生成个人小程序码
   */
  public createUserQrcode = (ctx: Context, token, params): Promise<string> => {
    return new Promise(async (resolve, reject) => {
      try {
        // 获取token信息
        const option = {
          url: `https://api.weixin.qq.com/wxa/getwxacode?access_token=${token}`,
          method: "post",
          json: true,
          headers: {
            "Access-Control-Allow-Origin": "*",
            "content-type": "application/json",
          },
          body: {
            path: `/pages/businessCard/businessCard?id=${params.id}&unitId=${params.unitId}`,
            env_version: config.mini.miniType,
            width: 280,
          },
        };

        const filePath = "/upload/" + this.createStr() + ".png";
        // console.log("filePath:", filePath);
        await request(option).pipe(fs.createWriteStream("public" + filePath));
        resolve(filePath);
        // console.log(res);
      } catch (error) {
        reject(error);
      }
    });
  };
  public createStr = () => {
    const date = Number(new Date());

    return MD5(date.toString());
  };
}

export default new BusinessCardUserController();
